import { 
  Controller, 
  Get, 
  Post, 
  Put, 
  Delete, 
  Body, 
  Param, 
  Query, 
  UploadedFile, 
  UseInterceptors,
  HttpCode,
  HttpStatus,
  Logger,
  ValidationPipe
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { 
  ApiTags, 
  ApiOperation, 
  ApiResponse, 
  ApiParam, 
  ApiQuery,
  ApiConsumes,
  ApiBody
} from '@nestjs/swagger';
import { BSCService } from '../services/bsc.service';
import { 
  CreateBSCTokenDto, 
  BuyBSCTokenDto,
  SellBSCTokenDto,
  ContributeBSCTokenDto,
  GetBSCTokensQueryDto,
  UpdateBSCTokenDto,
  GraduateBSCTokenDto,
  CancelBSCLaunchDto,
  ClaimRefundDto,
  PreviewTradeDto
} from '../dto/bsc.dto';

@ApiTags('BSC')
@Controller('api/bsc')
export class BSCController {
  private readonly logger = new Logger(BSCController.name);

  constructor(private readonly bscService: BSCService) {}

  /**
   * 获取BSC平台统计数据
   */
  @Get('stats')
  @ApiOperation({ summary: 'Get BSC platform statistics' })
  @ApiResponse({ status: 200, description: 'BSC platform statistics' })
  async getStats() {
    try {
      const stats = await this.bscService.getStats();
      return {
        success: true,
        data: stats
      };
    } catch (error) {
      this.logger.error('Failed to get BSC stats:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取BSC代币列表
   */
  @Get('tokens')
  @ApiOperation({ summary: 'Get BSC tokens list' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'search', required: false, type: String })
  @ApiQuery({ name: 'filter', required: false, enum: ['all', 'active', 'launched', 'cancelled'] })
  @ApiQuery({ name: 'sort', required: false, enum: ['newest', 'oldest', 'price_high', 'price_low', 'market_cap', 'volume'] })
  @ApiResponse({ status: 200, description: 'BSC tokens list' })
  async getTokens(@Query(ValidationPipe) query: GetBSCTokensQueryDto) {
    try {
      const result = await this.bscService.getTokens(query);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to get BSC tokens:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取特定BSC代币信息
   */
  @Get('tokens/:launchId')
  @ApiOperation({ summary: 'Get specific BSC token' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiResponse({ status: 200, description: 'BSC token details' })
  @ApiResponse({ status: 404, description: 'Token not found' })
  async getToken(@Param('launchId') launchId: string) {
    try {
      const token = await this.bscService.getToken(launchId);
      return {
        success: true,
        data: token
      };
    } catch (error) {
      this.logger.error(`Failed to get BSC token ${launchId}:`, error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取代币社交媒体信息
   */
  @Get('tokens/:launchId/social')
  @ApiOperation({ summary: 'Get token social media information' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiResponse({ status: 200, description: 'Token social media info' })
  async getTokenSocialInfo(@Param('launchId') launchId: string) {
    try {
      const socialInfo = await this.bscService.getTokenSocialInfo(parseInt(launchId));
      return {
        success: true,
        data: socialInfo
      };
    } catch (error) {
      this.logger.error(`Failed to get social info for token ${launchId}:`, error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取联合曲线信息
   */
  @Get('tokens/:launchId/bonding-curve')
  @ApiOperation({ summary: 'Get bonding curve information' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiResponse({ status: 200, description: 'Bonding curve information' })
  async getBondingCurveInfo(@Param('launchId') launchId: string) {
    try {
      const curveInfo = await this.bscService.getBondingCurveInfo(launchId);
      return {
        success: true,
        data: curveInfo
      };
    } catch (error) {
      this.logger.error(`Failed to get bonding curve info for token ${launchId}:`, error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 创建新的BSC代币发射
   */
  @Post('tokens')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create new BSC token launch' })
  @ApiResponse({ status: 201, description: 'Token launch created successfully' })
  @ApiResponse({ status: 400, description: 'Invalid input data' })
  async createToken(@Body(ValidationPipe) createTokenDto: CreateBSCTokenDto) {
    try {
      const result = await this.bscService.createTokenLaunch(createTokenDto);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to create BSC token:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 购买BSC代币
   */
  @Post('tokens/buy')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Buy BSC tokens' })
  @ApiResponse({ status: 200, description: 'Tokens purchased successfully' })
  @ApiResponse({ status: 400, description: 'Invalid purchase data' })
  async buyTokens(@Body(ValidationPipe) buyTokenDto: BuyBSCTokenDto) {
    try {
      const result = await this.bscService.buyTokens(buyTokenDto);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to buy BSC tokens:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 出售BSC代币
   */
  @Post('tokens/sell')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Sell BSC tokens' })
  @ApiResponse({ status: 200, description: 'Tokens sold successfully' })
  @ApiResponse({ status: 400, description: 'Invalid sell data' })
  async sellTokens(@Body(ValidationPipe) sellTokenDto: SellBSCTokenDto) {
    try {
      const result = await this.bscService.sellTokens(sellTokenDto);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to sell BSC tokens:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取交易预览
   */
  @Post('tokens/preview')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Get trade preview' })
  @ApiResponse({ status: 200, description: 'Trade preview calculated' })
  async getTradePreview(@Body(ValidationPipe) previewDto: PreviewTradeDto) {
    try {
      let result;
      if (previewDto.bnbAmount) {
        // Buy preview
        result = await this.bscService.getBuyPreview(
          previewDto.launchId.toString(),
          previewDto.bnbAmount.toString()
        );
      } else if (previewDto.tokenAmount) {
        // Sell preview
        result = await this.bscService.getSellPreview(
          previewDto.launchId.toString(),
          previewDto.tokenAmount.toString()
        );
      } else {
        throw new Error('Either bnbAmount or tokenAmount must be provided');
      }
      
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to get trade preview:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 手动毕业代币到PancakeSwap
   */
  @Post('tokens/graduate')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Manually graduate token to PancakeSwap' })
  @ApiResponse({ status: 200, description: 'Token graduated successfully' })
  async graduateToken(@Body(ValidationPipe) graduateDto: GraduateBSCTokenDto) {
    try {
      const result = await this.bscService.graduateToken(graduateDto);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to graduate BSC token:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 取消代币发射
   */
  @Post('tokens/cancel')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Cancel token launch' })
  @ApiResponse({ status: 200, description: 'Launch cancelled successfully' })
  async cancelLaunch(@Body(ValidationPipe) cancelDto: CancelBSCLaunchDto) {
    try {
      const result = await this.bscService.cancelLaunch(cancelDto);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to cancel BSC launch:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 申请退款
   */
  @Post('tokens/refund')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Claim refund' })
  @ApiResponse({ status: 200, description: 'Refund claimed successfully' })
  async claimRefund(@Body(ValidationPipe) refundDto: ClaimRefundDto) {
    try {
      const result = await this.bscService.claimRefund(refundDto);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to claim BSC refund:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取用户在特定发射中的贡献
   */
  @Get('tokens/:launchId/contributions/:userAddress')
  @ApiOperation({ summary: 'Get user contribution for specific launch' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiParam({ name: 'userAddress', description: 'User wallet address' })
  @ApiResponse({ status: 200, description: 'User contribution data' })
  async getUserContribution(
    @Param('launchId') launchId: string,
    @Param('userAddress') userAddress: string
  ) {
    try {
      const result = await this.bscService.getUserContribution(parseInt(launchId), userAddress);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to get user contribution:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取代币贡献者列表
   */
  @Get('tokens/:launchId/contributors')
  @ApiOperation({ summary: 'Get token contributors list' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiResponse({ status: 200, description: 'Contributors list' })
  async getContributors(@Param('launchId') launchId: string) {
    try {
      const result = await this.bscService.getContributors(parseInt(launchId));
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to get contributors:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 更新代币信息
   */
  @Put('tokens/:launchId')
  @ApiOperation({ summary: 'Update token information' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiResponse({ status: 200, description: 'Token updated successfully' })
  async updateToken(
    @Param('launchId') launchId: string,
    @Body(ValidationPipe) updateTokenDto: UpdateBSCTokenDto
  ) {
    try {
      // 这里需要验证更新权限（通常只有创建者可以更新）
      // const result = await this.bscService.updateToken(parseInt(launchId), updateTokenDto);
      return {
        success: true,
        message: 'Token update functionality not yet implemented'
      };
    } catch (error) {
      this.logger.error('Failed to update BSC token:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 同步代币信息（从合约同步到数据库）
   */
  @Post('tokens/:launchId/sync')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Sync token data from contract' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiResponse({ status: 200, description: 'Token data synced successfully' })
  async syncToken(@Param('launchId') launchId: string) {
    try {
      const result = await this.bscService.syncTokenFromContract(launchId);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      this.logger.error('Failed to sync BSC token:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取代币价格历史
   */
  @Get('tokens/:launchId/price-history')
  @ApiOperation({ summary: 'Get token price history' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiQuery({ name: 'timeframe', required: false, enum: ['1h', '24h', '7d', '30d'] })
  @ApiResponse({ status: 200, description: 'Token price history' })
  async getPriceHistory(
    @Param('launchId') launchId: string,
    @Query('timeframe') timeframe: string = '24h'
  ) {
    try {
      const history = await this.bscService.getPriceHistory(launchId, timeframe);
      return {
        success: true,
        data: history
      };
    } catch (error) {
      this.logger.error('Failed to get price history:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 获取交易历史
   */
  @Get('tokens/:launchId/trades')
  @ApiOperation({ summary: 'Get token trade history' })
  @ApiParam({ name: 'launchId', description: 'Token launch ID' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiResponse({ status: 200, description: 'Token trade history' })
  async getTradeHistory(
    @Param('launchId') launchId: string,
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 20
  ) {
    try {
      const trades = await this.bscService.getTradeHistory(launchId, page, limit);
      return {
        success: true,
        data: trades
      };
    } catch (error) {
      this.logger.error('Failed to get trade history:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 上传代币图片
   */
  @Post('upload')
  @UseInterceptors(FileInterceptor('image'))
  @ApiConsumes('multipart/form-data')
  @ApiOperation({ summary: 'Upload token image' })
  @ApiBody({
    description: 'Token image file',
    type: 'multipart/form-data',
    schema: {
      type: 'object',
      properties: {
        image: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiResponse({ status: 200, description: 'Image uploaded successfully' })
  async uploadImage(@UploadedFile() file: Express.Multer.File) {
    try {
      if (!file) {
        return {
          success: false,
          error: 'No file uploaded'
        };
      }
      
      // const result = await this.bscService.uploadImage(file);
      return {
        success: true,
        message: 'Image upload functionality not yet implemented',
        data: {
          filename: file.filename,
          size: file.size,
          mimetype: file.mimetype
        }
      };
    } catch (error) {
      this.logger.error('Failed to upload image:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }
}